import React, { useCallback, useMemo } from 'react'
import { Input as FormilyInput } from '@formily/antd'
import { DnFC } from '@designable/react'
import { useParentForm } from '@formily/react'
import { Typography } from 'antd'
import createEvent, { useT } from '@designable/event-system'

export interface InputWithAddonClickProps
  extends React.ComponentProps<typeof FormilyInput> {
  /** 前缀槽位(addonBefore)点击时执行的表达式 */
  addonBeforeClickExpression?: string
  /** 后缀槽位(addonAfter)点击时执行的表达式 */
  addonAfterClickExpression?: string
}

const isEmpty = (v: any) => v === undefined || v === null || v === ''

const Com: DnFC<InputWithAddonClickProps> = (props) => {
  const form = useParentForm()
  const createT = useT()

  const {
    addonBefore,
    addonAfter,
    addonBeforeClickExpression,
    addonAfterClickExpression,
    ...rest
  } = props

  const value = (props as any)?.value

  const exec = useCallback(
    async (expression?: string, event?: React.MouseEvent) => {
      if (isEmpty(expression)) return
      try {
        await createEvent(expression as string, {
          form,
          value,
          event,
          createT,
        })
      } catch (e) {
        // eslint-disable-next-line no-console
        console.error('执行表达式失败:', e)
      }
    },
    [form, value]
  )

  const clickableStyle = useMemo<React.CSSProperties>(
    () => ({ cursor: 'pointer' }),
    []
  )

  const renderMaybeClickable = (
    node: React.ReactNode,
    expression?: string
  ): React.ReactNode => {
    if (isEmpty(node)) return node
    if (isEmpty(expression)) return node

    return (
      <Typography.Text
        onClick={(e) => exec(expression, e)}
        style={clickableStyle}
      >
        {node}
      </Typography.Text>
    )
  }
  return (
    <FormilyInput
      {...(rest as any)}
      addonBefore={renderMaybeClickable(
        addonBefore,
        addonBeforeClickExpression
      )}
      addonAfter={renderMaybeClickable(addonAfter, addonAfterClickExpression)}
    />
  )
}

export const Input: any = Object.assign(Com, {
  TextArea: FormilyInput.TextArea,
})

export default Input
